package client.gui;

public class GameLoop implements Runnable {

	private boolean running;
	private int gameHertz;
	private int fps;

	private GameFrame gui;

	public GameLoop(GameFrame gui, int gameHertz, int fps) {
		this.gui = gui;
		this.gameHertz = gameHertz;
		this.fps = fps;
	}

	public void setRunning(boolean running) {
		this.running = running;
	}

	@Override
	public void run() {
		final double TIME_BETWEEN_UPDATES = 1000000000 / gameHertz;
		final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / fps;
		final int MAX_UPDATES_BEFORE_RENDER = 5;
		double lastUpdateTime = System.nanoTime();
		double lastRenderTime = System.nanoTime();
		int lastSecondTime = (int) (lastUpdateTime / 1000000000);
		while (running) {
			double now = System.nanoTime();
			int updateCount = 0;
			while(now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER) {
				gui.updateGame();
				lastUpdateTime += TIME_BETWEEN_UPDATES;
				updateCount++;
			}
			if (lastUpdateTime - now > TIME_BETWEEN_UPDATES) {
				lastUpdateTime = now - TIME_BETWEEN_UPDATES;
			}
			gui.repaint();
			lastRenderTime = now;
			int thisSecond = (int) (lastUpdateTime / 1000000000);
			if (thisSecond > lastSecondTime) {
				lastSecondTime = thisSecond;
			}
			while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
			{
				Thread.yield();
				try {
					Thread.sleep(1);
				} catch(Exception e) {}
				now = System.nanoTime();
			}
		}
	}
}
